{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<script>\n",
       "code_show=true; \n",
       "function code_toggle() {\n",
       " if (code_show){\n",
       " $('div.input').hide();\n",
       " } else {\n",
       " $('div.input').show();\n",
       " }\n",
       " code_show = !code_show\n",
       "} \n",
       "$( document ).ready(code_toggle);\n",
       "</script>\n",
       "<form action=\"javascript:code_toggle()\"><input type=\"submit\" value=\"Click here to toggle on/off the raw code for QISKit exercises.\"></form>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML('''<script>\n",
    "code_show=true; \n",
    "function code_toggle() {\n",
    " if (code_show){\n",
    " $('div.input').hide();\n",
    " } else {\n",
    " $('div.input').show();\n",
    " }\n",
    " code_show = !code_show\n",
    "} \n",
    "$( document ).ready(code_toggle);\n",
    "</script>\n",
    "<form action=\"javascript:code_toggle()\"><input type=\"submit\" value=\"Click here to toggle on/off the raw code for QISKit exercises.\"></form>''')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 10. Quantum error correction\n",
    "\n",
    "In the last chapter, we saw how the impossibility of copying an unknown quantum state adds a layer of security to quantum communication when compared to classical ones. At first sight, this feature turns into a drawback once we step into the realm of error correction. In fact, classically one can protect information by making many copies of the bits of interest. The probability that an error will happen to all the copies quickly becomes extremely unlikely with an increasing number of copies. However, the no-cloning theorem prohibits us from using the same technique for quantum bits.\n",
    "Interestingly, error correcting procedure exists also in quantum computation. In this case, quantum entanglement and quantum superposition are used as resources to fight against unwanted errors. In this chapter, we take a closer look at quantum error correction for the simple cases of a bit-flip error and a phase error following a five-qubit protocol outlined in Ref. [1]."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 10.1 The bit-flip error in the three-bit code\n",
    "\n",
    "<img src=\"figures/10/bit_flip2.jpeg\"  width=\"950\">\n",
    "$$\\text{1. Error correcting circuit for a bit-flip error.}$$\n",
    "\n",
    "Let us analyze the case of transmission of quantum information, in the form of a qubit, through a noisy channel. Because of the presence of noise, an error could occur during the communication which could change the state of the qubit in an unpredictable way. We must be able to restore its state without measuring the qubit.\n",
    "\n",
    "\n",
    "Let us make a few assumptions. First of all, we are going to assume that if more than one qubits are transferred, errors happen independently on each qubit. Also, here we are going to consider only single bit-flip ($X$) errors.\n",
    "\n",
    "Take the qubit we want to transfer to be in the state\n",
    "\n",
    "\\begin{equation}\n",
    "\\lvert \\psi \\rangle= \\alpha\\lvert 0\\rangle +\\beta \\lvert 1\\rangle\n",
    "\\end{equation}\n",
    "\n",
    "As a first step, we encode this qubit in a three-qubit entangled state using two extra ancilla qubits in the state $\\lvert 0 \\rangle$ and CNOT gates from the first qubits to the ancillas ($CX_{12}CX_{13}$)\n",
    "\n",
    "\\begin{equation}\n",
    "\\lvert\\psi_1\\rangle=\\alpha\\lvert000\\rangle+\\beta\\lvert110\\rangle\n",
    "\\end{equation}\n",
    "\n",
    "\n",
    "The three qubits are then sent through the noisy communication channel and retrieved on the receiver's side. During the communication, a bit-flip error could have occurred on any of the three qubits giving one of the following states\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$\\lvert \\psi_{2} \\rangle =\\alpha\\lvert 000\\rangle+\\beta\\lvert 111\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_{2} \\rangle =\\alpha\\lvert100\\rangle+\\beta\\lvert011\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert\\psi_{2} \\rangle =\\alpha\\lvert010\\rangle+\\beta\\lvert101\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert\\psi_{2} \\rangle =\\alpha\\lvert001\\rangle+\\beta\\lvert110\\rangle$\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "\n",
    "In order to correct the state received at the other end of the quantum communication channel from possible errors, two more ancilla qubits in the state $\\lvert 0\\rangle$ are added to the system. Moreover, they are entangled with the three bit received by using the following gates: $CX_{14}CX_{24}CX_{15}CX_{35}$. The state of the system is now\n",
    "\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$\\lvert\\psi_{3} \\rangle =\\alpha \\lvert000 \\rangle \\lvert 00\\rangle+\\beta\\lvert111 \\rangle \\lvert 00\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert\\psi_{3} \\rangle =\\alpha\\lvert001 \\rangle \\lvert 01\\rangle+\\beta\\lvert110 \\rangle \\lvert 01\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert\\psi_{3} \\rangle =\\alpha\\lvert010 \\rangle \\lvert 10\\rangle+\\beta\\lvert101 \\rangle \\lvert 10\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert\\psi_{3} \\rangle =\\alpha\\lvert100 \\rangle \\lvert 11\\rangle+\\beta\\lvert011 \\rangle \\lvert 11\\rangle$\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "The two ancilla qubits just added are then measured. They give the \"error syndrom\", which can be used to diagnose and then correct any error occurred on the three qubits. There are four possible outcomes for the error syndrome:\n",
    "\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$00$: $\\lvert\\psi_{4} \\rangle =\\alpha \\lvert000 \\rangle +\\beta\\lvert111 \\rangle $\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$01$: $\\lvert\\psi_{4} \\rangle =\\alpha\\lvert001 \\rangle +\\beta\\lvert110 \\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$10$: $\\lvert\\psi_{4} \\rangle =\\alpha\\lvert010 \\rangle +\\beta\\lvert101 \\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$11$: $\\lvert\\psi_{4} \\rangle =\\alpha\\lvert100 \\rangle +\\beta\\lvert011 \\rangle$\n",
    "\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "Therefore, the state of the three qubits can be corrected by applying the corresponding gate\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$00$: No correction is needed\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$01$: Apply $X$ gate to the third qubit\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$10$: Apply $X$ gate to the second qubit\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$11$: Apply $X$ gate to the first qubit\n",
    "\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "After which the state of the system will be\n",
    "\n",
    "\\begin{equation}\n",
    "\\lvert\\psi_5\\rangle=\\alpha\\lvert000\\rangle+\\beta\\lvert111\\rangle\n",
    "\\end{equation}\n",
    "\n",
    "As originally sent. Now, to find the state of the qubit which was intended to be transferred, we decode it from the three-qubit state by disentangling the qubit with the two ancillas. Thus we apply $CX_{12}CX_{13}$ and obtain\n",
    "\n",
    "\\begin{equation}\n",
    "\\lvert\\psi_6\\rangle = \\alpha\\lvert0\\rangle+\\beta\\lvert1\\rangle = \\lvert\\psi \\rangle\n",
    "\\end{equation}\n",
    "\n",
    "We have successfully communicated the state of the qubit $\\lvert\\psi \\rangle$ through a noisy channel, protecting it from any single bit-flip error."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <span style=\"color:blue\"> QISKit: implement the quantum error correction code for bit-flip error </span>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### <span style=\"color:blue\"> 1) Correct an X error on the second qubit in the state $ \\frac{1}{\\sqrt{2}}\\left( \\lvert 0 \\rangle + \\lvert 1 \\rangle \\right)$ </span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OPENQASM 2.0;\n",
      "include \"qelib1.inc\";\n",
      "qreg q[5];\n",
      "creg c0[1];\n",
      "creg c1[1];\n",
      "creg c2[1];\n",
      "h q[0];\n",
      "cx q[0],q[1];\n",
      "cx q[0],q[2];\n",
      "x q[1];\n",
      "cx q[0],q[3];\n",
      "cx q[1],q[3];\n",
      "cx q[0],q[4];\n",
      "cx q[2],q[4];\n",
      "measure q[3] -> c0[0];\n",
      "measure q[4] -> c1[0];\n",
      "if(c0==1) x q[1];\n",
      "if(c1==1) x q[2];\n",
      "cx q[0],q[1];\n",
      "cx q[0],q[2];\n",
      "measure q[0] -> c2[0];\n",
      "\n",
      "\n",
      "The measured outcomes of the circuits are: {'0 0 1': 501, '1 0 1': 523}\n"
     ]
    }
   ],
   "source": [
    "from qiskit import *\n",
    "\n",
    "# Quantum program setup \n",
    "Q_program = QuantumProgram()\n",
    "\n",
    "# Creating registers\n",
    "q = Q_program.create_quantum_register('q', 5)\n",
    "c0 = Q_program.create_classical_register('c0', 1)\n",
    "c1 = Q_program.create_classical_register('c1', 1)\n",
    "c2 = Q_program.create_classical_register('c2', 1)\n",
    "\n",
    "# Creates the quantum circuit\n",
    "bit_flip = Q_program.create_circuit('bit_flip', [q], [c0,c1,c2])\n",
    "\n",
    "# Prepares qubit in the desired initial state \n",
    "bit_flip.h(q[0])\n",
    "\n",
    "# Encodes the qubit in a three-qubit entangled state  \n",
    "bit_flip.cx(q[0], q[1])\n",
    "bit_flip.cx(q[0], q[2])\n",
    "\n",
    "# Bit-flip error on the second qubit\n",
    "bit_flip.x(q[1])\n",
    "\n",
    "# Adds additional two qubits for error-correction\n",
    "bit_flip.cx(q[0], q[3])\n",
    "bit_flip.cx(q[1], q[3])\n",
    "bit_flip.cx(q[0], q[4])\n",
    "bit_flip.cx(q[2], q[4])\n",
    "\n",
    "# Measure the two additional qubits\n",
    "bit_flip.measure(q[3], c0[0])\n",
    "bit_flip.measure(q[4], c1[0])\n",
    "\n",
    "# Do error correction\n",
    "bit_flip.x(q[1]).c_if(c0, 1)\n",
    "bit_flip.x(q[2]).c_if(c1, 1)\n",
    "\n",
    "# Decodes the qubit from the three-qubit entangled state  \n",
    "bit_flip.cx(q[0], q[1])\n",
    "bit_flip.cx(q[0], q[2])\n",
    "\n",
    "# Check the state of the initial qubit\n",
    "bit_flip.measure(q[0], c2[0])\n",
    "\n",
    "# Shows gates of the circuit\n",
    "circuits = ['bit_flip']\n",
    "print(Q_program.get_qasms(circuits)[0])\n",
    "\n",
    "# Parameters for execution on simulator\n",
    "backend = 'local_qasm_simulator' \n",
    "shots = 1024 # the number of shots in the experiment \n",
    "\n",
    "# Run the algorithm\n",
    "result = Q_program.execute(circuits, backend=backend, shots=shots)\n",
    "\n",
    "#Shows the results obtained from the quantum algorithm \n",
    "counts = result.get_counts('bit_flip')\n",
    "\n",
    "print('\\nThe measured outcomes of the circuits are:', counts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 10.2 The phase error in the three-bit code\n",
    "\n",
    "<img src=\"figures/10/phase_error2.jpeg\"  width=\"1100\">\n",
    "$$\\text{2. Error correcting circuit for a phase error.}$$\n",
    "\n",
    "Consider now the case of a phase error. Phase error transforms the basis states as\n",
    "\n",
    "\\begin{eqnarray}\n",
    "\\lvert 0 &\\rangle&\\rightarrow U\\lvert0\\rangle= e^{i\\phi}\\lvert 0 \\rangle  \\notag \\\\\n",
    "\\lvert 1 &\\rangle&\\rightarrow U\\lvert1\\rangle=e^{-i\\phi}\\lvert 1 \\rangle\n",
    "\\end{eqnarray}\n",
    "\n",
    "Let us see how we can protect a qubit in the generic state $\\lvert \\psi \\rangle=\\lvert \\alpha \\lvert0\\rangle+ \\beta \\lvert1\\rangle$ from this kind of errors. We are going to assume again that phase error occurs independently on each qubit and that only single phase error may occur.\n",
    "\n",
    "Before sending the qubit through the noisy channel, we encode it in an entangled state similar to the previous one by using two ancillas in the state $\\lvert 0 \\rangle$.  To do so we apply $CX_{12}CX_{13}$ and then Hadamard gate on all three qubits, obtaining the encoded state\n",
    "\n",
    "\\begin{eqnarray}\n",
    "\\lvert \\psi_1 \\rangle = \\frac{1}{\\sqrt{2^3}}\\left\\{ \\alpha \\left[ (\\lvert0\\rangle+\\lvert1\\rangle)(\\lvert0\\rangle+\\lvert1\\rangle)(\\lvert0\\rangle+\\lvert1\\rangle) \\right] +  \\beta \\left[ (\\lvert0\\rangle-\\lvert1\\rangle)(\\lvert0\\rangle-\\lvert1\\rangle)(\\lvert0\\rangle-\\lvert1\\rangle) \\right] \\right\\}\n",
    "\\end{eqnarray}\n",
    "\n",
    "\n",
    "The three qubits are then sent through the noisy communication channel and retrieved on the receiver's side. During the communication, a phase error could have occurred on any of the three qubits giving one of the following states\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$\\lvert \\psi_{2} \\rangle = \\frac{1}{\\sqrt{2^3}}\\left\\{ \\alpha \\left[ (\\lvert0\\rangle+\\lvert1\\rangle)(\\lvert0\\rangle+\\lvert1\\rangle)(\\lvert0\\rangle+\\lvert1\\rangle) \\right] +  \\beta \\left[ (\\lvert0\\rangle-\\lvert1\\rangle)(\\lvert0\\rangle-\\lvert1\\rangle)(\\lvert0\\rangle-\\lvert1\\rangle) \\right] \\right\\}$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_{2} \\rangle = \\frac{1}{\\sqrt{2^3}}\\left\\{ \\alpha \\left[ (e^{i\\phi}\\lvert0\\rangle+e^{-i\\phi}\\lvert1\\rangle)(\\lvert0\\rangle+\\lvert1\\rangle)(\\lvert0\\rangle+\\lvert1\\rangle) \\right] +  \\beta \\left[ (e^{i\\phi} \\lvert0\\rangle-e^{-i\\phi}\\lvert1\\rangle)(\\lvert0\\rangle-\\lvert1\\rangle)(\\lvert0\\rangle-\\lvert1\\rangle) \\right] \\right\\}$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_{2} \\rangle =\\frac{1}{\\sqrt{2^3}}\\left\\{ \\alpha \\left[ (\\lvert0\\rangle+\\lvert1\\rangle)(e^{i\\phi}\\lvert0\\rangle+e^{-i\\phi}\\lvert1\\rangle)(\\lvert0\\rangle+\\lvert1\\rangle) \\right] +  \\beta \\left[ (\\lvert0\\rangle-\\lvert1\\rangle)(e^{i\\phi}\\lvert0\\rangle-e^{-i\\phi}\\lvert1\\rangle)(\\lvert0\\rangle-\\lvert1\\rangle) \\right] \\right\\}$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_{2} \\rangle = \\frac{1}{\\sqrt{2^3}}\\left\\{ \\alpha \\left[ (\\lvert0\\rangle+\\lvert1\\rangle)(\\lvert0\\rangle+\\lvert1\\rangle)(e^{i\\phi} \\lvert0\\rangle+e^{-i\\phi}\\lvert1\\rangle) \\right] +  \\beta \\left[ (\\lvert0\\rangle-\\lvert1\\rangle)(\\lvert0\\rangle-\\lvert1\\rangle)(e^{i\\phi} \\lvert0\\rangle-e^{-i\\phi}\\lvert1\\rangle) \\right] \\right\\}$\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "\n",
    "In order to correct the state received at the other end of the quantum communication channel from possible errors, we first apply the Hadamard gate on all three qubits again. Giving:\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$\\lvert \\psi_{3} \\rangle =  \\alpha \\lvert000\\rangle +  \\beta \\lvert111\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_3 \\rangle = \\frac{1}{\\sqrt{2^3}}\\left\\{ \\alpha \\left[   (e^{i\\phi}\\lvert0\\rangle + e^{i \\phi} \\lvert1\\rangle + e^{-i\\phi}\\lvert0\\rangle - e^{-i\\phi}\\lvert1\\rangle) \\lvert00\\rangle \\right] +  \\beta \\left[ (e^{i\\phi}\\lvert0\\rangle + e^{i\\phi}\\lvert1\\rangle - e^{-i\\phi}\\lvert 0 \\rangle + e^{-i\\phi}\\lvert 1 \\rangle) \\lvert11\\rangle \\right] \\right\\}$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_{3} \\rangle =\\frac{1}{\\sqrt{2^3}}\\left\\{ \\alpha \\left[ \\lvert0\\rangle  (e^{i\\phi}\\lvert0\\rangle + e^{i \\phi} \\lvert1\\rangle + e^{-i\\phi}\\lvert0\\rangle - e^{-i\\phi}\\lvert1\\rangle)  \\lvert0\\rangle \\right] +  \\beta \\left[ \\lvert1\\rangle  (e^{i\\phi}\\lvert0\\rangle + e^{i \\phi} \\lvert1\\rangle + e^{-i\\phi}\\lvert0\\rangle - e^{-i\\phi}\\lvert1\\rangle)  \\lvert1\\rangle \\right] \\right\\}$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_3 \\rangle = \\frac{1}{\\sqrt{2^3}}\\left\\{ \\alpha \\left[ \\lvert00\\rangle  (e^{i\\phi}\\lvert0\\rangle + e^{i \\phi} \\lvert1\\rangle + e^{-i\\phi}\\lvert0\\rangle - e^{-i\\phi}\\lvert1\\rangle) \\right] +  \\beta \\left[ \\lvert11\\rangle (e^{i\\phi}\\lvert0\\rangle + e^{i\\phi}\\lvert1\\rangle - e^{-i\\phi}\\lvert 0 \\rangle + e^{-i\\phi}\\lvert 1 \\rangle) \\right] \\right\\}$\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "Expanding the phase as $e^{i \\phi} = \\cos \\phi + i \\sin \\phi$ and simplifying terms we obtain\n",
    "\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$\\lvert \\psi_{3} \\rangle =  \\alpha \\lvert000\\rangle +  \\beta \\lvert111\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_3 \\rangle =\\alpha(\\cos \\phi \\lvert000 \\rangle+i\\sin \\phi \\lvert100\\rangle)+\\beta(\\cos \\phi \\lvert111\\rangle+i\\sin \\phi \\lvert011\\rangle)$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_3 \\rangle =\\alpha(\\cos \\phi \\lvert000 \\rangle+i\\sin \\phi \\lvert010\\rangle)+\\beta(\\cos \\phi \\lvert111\\rangle+i\\sin \\phi \\lvert101\\rangle)$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert \\psi_3 \\rangle =\\alpha(\\cos \\phi \\lvert000 \\rangle+i\\sin \\phi \\lvert001\\rangle)+\\beta(\\cos \\phi \\lvert111\\rangle+i\\sin \\phi \\lvert110\\rangle)$\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "\n",
    "\n",
    "Two more ancilla qubits in the state $\\lvert 0\\rangle$ are added to the system. Moreover, they are entangled with the three bit received by using the following gates: $CX_{14}CX_{24}CX_{15}CX_{35}$. The state of the system is now\n",
    "\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$\\lvert\\psi_{4} \\rangle =\\alpha \\lvert000 \\rangle \\lvert 00\\rangle+\\beta\\lvert111 \\rangle \\lvert 00\\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert\\psi_{4} \\rangle =\\alpha(\\cos \\phi \\lvert000 \\rangle \\lvert 00\\rangle+i\\sin \\phi \\lvert100 \\rangle \\lvert 11\\rangle)+\\beta(\\cos \\phi \\lvert111 \\rangle \\lvert 00\\rangle+i\\sin \\phi \\lvert011 \\rangle \\lvert 11\\rangle)$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert\\psi_{4} \\rangle =\\alpha(\\cos \\phi \\lvert000 \\rangle \\lvert 00\\rangle+i\\sin \\phi \\lvert010 \\rangle \\lvert 10\\rangle)+\\beta(\\cos \\phi \\lvert111 \\rangle \\lvert 00\\rangle+i\\sin \\phi \\lvert101 \\rangle \\lvert 10\\rangle)$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$\\lvert\\psi_{4} \\rangle =\\alpha(\\cos \\phi \\lvert000  \\rangle \\lvert 00\\rangle+i\\sin \\phi \\lvert001 \\rangle \\lvert 01\\rangle)+\\beta(\\cos \\phi \\lvert111 \\rangle \\lvert 00\\rangle+i\\sin \\phi \\lvert110 \\rangle \\lvert 01\\rangle)$\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "The two ancilla qubits just added are then measured. They give the \"error syndrome\", which can be used to diagnose and then correct any error occurred on the three qubits. There are four possible outcomes for the error syndrome:\n",
    "\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$00$: $\\lvert\\psi_{5} \\rangle =\\alpha \\lvert000 \\rangle +\\beta\\lvert111 \\rangle $\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$11$: $\\lvert\\psi_{5} \\rangle =\\alpha\\lvert100 \\rangle +\\beta\\lvert011 \\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$10$: $\\lvert\\psi_{5} \\rangle =\\alpha\\lvert010 \\rangle +\\beta\\lvert101 \\rangle$\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$01$: $\\lvert\\psi_{5} \\rangle =\\alpha\\lvert001 \\rangle +\\beta\\lvert110 \\rangle$\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "Therefore, the state of the three qubits can be corrected by applying the corresponding gate\n",
    "\n",
    "<ol>\n",
    "<li>\n",
    "$00$: No correction is needed\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$11$: Apply $X$ gate to the first qubit\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$10$: Apply $X$ gate to the second qubit\n",
    "</li>\n",
    "\n",
    "<li>\n",
    "$01$: Apply $X$ gate to the third qubit\n",
    "\n",
    "</li>\n",
    "\n",
    "</ol>\n",
    "\n",
    "After which the state of the system will be\n",
    "\n",
    "\\begin{equation}\n",
    "\\lvert\\psi_6\\rangle=\\alpha\\lvert000\\rangle+\\beta\\lvert111\\rangle\n",
    "\\end{equation}\n",
    "\n",
    "As originally sent. Now, to find the state of the qubit which was intended to be transferred, we decode it from the three-qubit state by disentangling the qubit with the two ancillas. Thus we apply $CX_{12}CX_{13}$ and obtain\n",
    "\n",
    "\\begin{equation}\n",
    "\\lvert\\psi_7\\rangle = \\alpha\\lvert0\\rangle+\\beta\\lvert1\\rangle = \\lvert\\psi \\rangle\n",
    "\\end{equation}\n",
    "\n",
    "We have successfully communicated the state of the qubit $\\lvert\\psi \\rangle$ through a noisy channel, protecting it from any single phase error."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <span style=\"color:blue\"> QISKit: implement the quantum error correction code for phase error </span>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### <span style=\"color:blue\"> 2) Correct a Z error on the second qubit in the state $ \\frac{1}{\\sqrt{2}}\\left( \\lvert 0 \\rangle + \\lvert 1 \\rangle \\right)$ </span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OPENQASM 2.0;\n",
      "include \"qelib1.inc\";\n",
      "qreg q[5];\n",
      "creg c0[1];\n",
      "creg c1[1];\n",
      "creg c2[1];\n",
      "h q[0];\n",
      "cx q[0],q[1];\n",
      "cx q[0],q[2];\n",
      "h q[0];\n",
      "h q[1];\n",
      "h q[2];\n",
      "z q[1];\n",
      "h q[0];\n",
      "h q[1];\n",
      "h q[2];\n",
      "cx q[0],q[3];\n",
      "cx q[1],q[3];\n",
      "cx q[0],q[4];\n",
      "cx q[2],q[4];\n",
      "measure q[3] -> c0[0];\n",
      "measure q[4] -> c1[0];\n",
      "if(c0==1) x q[1];\n",
      "if(c1==1) x q[2];\n",
      "cx q[0],q[1];\n",
      "cx q[0],q[2];\n",
      "measure q[0] -> c2[0];\n",
      "\n",
      "\n",
      "The measured outcomes of the circuits are: {'0 0 1': 550, '1 0 1': 474}\n"
     ]
    }
   ],
   "source": [
    "from qiskit import *\n",
    "\n",
    "# Quantum program setup \n",
    "Q_program = QuantumProgram()\n",
    "\n",
    "# Creating registers\n",
    "q = Q_program.create_quantum_register('q', 5)\n",
    "c0 = Q_program.create_classical_register('c0', 1)\n",
    "c1 = Q_program.create_classical_register('c1', 1)\n",
    "c2 = Q_program.create_classical_register('c2', 1)\n",
    "\n",
    "# Creates the quantum circuit\n",
    "bit_flip = Q_program.create_circuit('bit_flip', [q], [c0,c1,c2])\n",
    "\n",
    "# Prepares qubit in the desired initial state \n",
    "bit_flip.h(q[0])\n",
    "\n",
    "# Encodes the qubit in a three-qubit entangled state  \n",
    "bit_flip.cx(q[0], q[1])\n",
    "bit_flip.cx(q[0], q[2])\n",
    "\n",
    "# Go to Hadamard basis\n",
    "bit_flip.h(q[0])\n",
    "bit_flip.h(q[1])\n",
    "bit_flip.h(q[2])\n",
    "\n",
    "# Phase error on the second qubit\n",
    "bit_flip.z(q[1])\n",
    "\n",
    "# Converts phase error in bit-flip error\n",
    "bit_flip.h(q[0])\n",
    "bit_flip.h(q[1])\n",
    "bit_flip.h(q[2])\n",
    "\n",
    "# Adds additional two qubits for error-correction\n",
    "bit_flip.cx(q[0], q[3])\n",
    "bit_flip.cx(q[1], q[3])\n",
    "bit_flip.cx(q[0], q[4])\n",
    "bit_flip.cx(q[2], q[4])\n",
    "\n",
    "# Measure the two additional qubits\n",
    "bit_flip.measure(q[3], c0[0])\n",
    "bit_flip.measure(q[4], c1[0])\n",
    "\n",
    "# Do error correction\n",
    "bit_flip.x(q[1]).c_if(c0, 1)\n",
    "bit_flip.x(q[2]).c_if(c1, 1)\n",
    "\n",
    "# Decodes the qubit from the three-qubit entangled state  \n",
    "bit_flip.cx(q[0], q[1])\n",
    "bit_flip.cx(q[0], q[2])\n",
    "\n",
    "# Check the state of the initial qubit\n",
    "bit_flip.measure(q[0], c2[0])\n",
    "\n",
    "# Shows gates of the circuit\n",
    "circuits = ['bit_flip']\n",
    "print(Q_program.get_qasms(circuits)[0])\n",
    "\n",
    "# Parameters for execution on simulator\n",
    "backend = 'local_qasm_simulator' \n",
    "shots = 1024 # the number of shots in the experiment \n",
    "\n",
    "# Run the algorithm\n",
    "result = Q_program.execute(circuits, backend=backend, shots=shots)\n",
    "\n",
    "#Shows the results obtained from the quantum algorithm \n",
    "counts = result.get_counts('bit_flip')\n",
    "\n",
    "print('\\nThe measured outcomes of the circuits are:', counts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercises\n",
    "\n",
    "\n",
    "<ol>\n",
    "<li> \n",
    "Show the evolution of the state of the system for the transmission of the state $\\lvert 1 \\rangle$ through a noisy communication channel. Consider the case where:\n",
    "\n",
    "<ol>\n",
    "<li> \n",
    "A bit-flip error occurs to the first qubit of the encoded state\n",
    "</li>\n",
    "\n",
    "<li> \n",
    "A phase error occurs to the third qubit of the encoded state\n",
    "</li>\n",
    "</ol>\n",
    "\n",
    "</li>\n",
    "\n",
    "\n",
    "<li> \n",
    "Write a QISKit program that implements the exercises described above\n",
    "</li>\n",
    "\n",
    "</ol>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## References\n",
    "\n",
    "[1] A. M. Steane, arXiv:quant-ph/0304016v2 (2003).\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
